/**
 * Class Ajax
 * This class is used to create a ajax requests
 *
 * Example:
 *
 * var ajax = new Ajax();
 * ajax.open("http://api.com/test.json");
 * ajax.onSuccess = function(data){
 *     //data.status -> "success"
 *     //data.data -> result form server
 * };
 * ajax.onError = function(data){
 *     //data.status -> "error"
 *     //data.data -> null
 * };
 * ajax.send();
 */
Ajax = (function() {
	/**
	 * Class Ajax constructor
	 *
	 * @constructor
	 */
    function Ajax() {
        var _this = this;
        this.xmlhttp = (typeof window.createRequest === "function" ? window.createRequest() : void 0) || (XMLHttpRequest ? new XMLHttpRequest() : void 0);
        this.xmlhttp.onreadystatechange = function() {
            if (_this.xmlhttp.readyState !== 4) {
                return void 0;
            }
            if (!(_this.xmlhttp.status === 200 || _this.xmlhttp.status === 304)) {
                if(_this.successListener)
                    _this.successListener.call(_this, {
                        status: _this.xmlhttp.status,
                        data: {}
                    });
            }
            if (_this.xmlhttp.responseText) {
                if(_this.successListener)
                    try{
                        _this.successListener.call(_this, {
                            status: "success",
                            data: JSON.parse(_this.xmlhttp.responseText)
                        });
                    }catch (e){
                        _this.successListener.call(_this, {
                            status: "success",
                            data: _this.xmlhttp.responseText
                        });
                    }
            }
        };
        if ('onerror' in this.xmlhttp) {
            this.xmlhttp.onerror = function() {
                if(_this.errorListener)
                    _this.errorListener.call(this, {
                        status: 'error',
                        data: null
                    });
            };
        }
        this.method = "GET";
    }
	/**
	 * Set On Success Listener this event will be fired when ajax return result
	 *
	 * @param listener {Function} Listener Function
	 */
    Ajax.prototype.setOnSuccessListener = function(listener) {
		if(!(listener instanceof Function)) throw "listener is not a fucntion.";
        this.successListener = listener;
    };
	/**
	 * Set On Success Listener this event will be fired when ajax return result
	 *
	 * @param listener {Function} Listener Function
	 */
    Ajax.prototype.setOnErrorListener = function(listener) {
		if(!(listener instanceof Function)) throw "listener is not a fucntion.";
        this.errorListener = listener;
    };
	/**
	 * Set request Method POST|GET|DELETE|PUT
	 *
	 * @param method {String} Method Type
	 */
    Ajax.prototype.setMethod = function(method) {
        this.method = method.toUpperCase();
    };
	/**
	 * Set Headers for request
	 *
	 * @param headers {Object} Header key value proparties
	 */
    Ajax.prototype.setRequestHeader = function(headers) {
        var key, value, _ref;
        this.headers = headers;
        _ref = this.headers;
        for (key in _ref) {
            value = _ref[key];
            this.xmlhttp.setRequestHeader(key, value);
        }
    };
	/**
	 * Prepare ajax request set url, data headers and query data
	 *
	 * @param url {String} Requested url
	 * @param [data] {Object} Query data
	 */
    Ajax.prototype.open = function(url, data) {
        this.data = this.toQuery(data);
        if (this.method === "GET") {
            this.url = "" + url + (data ? (__indexOf.call(url, "?") >= 0 ? "&" : "?") : "") + (encodeURI(this.data));
        }else{
            this.url = url;
        }
        this.xmlhttp.open(this.method, this.url, true);
        this.setRequestHeader({
            "X-Requested-With": "XMLHttpRequest"
        });
        if (this.method === "POST") {
            this.setRequestHeader({
                "Content-type": "application/x-www-form-urlencoded"
            });
        }
    };
	/**
	 * Create query string form object
	 * Example:
	 * var query = {
	 *     data: "data",
	 *     options: {
	 *     		value1: "1",
	 *     		value2: "2"
	 *     }
	 * }
	 * toQuery(query) -> "data=data&options[value1]=1&options[value2]=2"
	 *
	 * @param data {Object} Query data
	 * @param [deep] {String} Deep property
	 * @returns {string} Query String
	 */
    Ajax.prototype.toQuery = function(data, deep) {
        var key, value;
        return ((function() {
            var _results;
            _results = [];
            for (key in data) {
                value = data[key];
                _results.push(typeof value === "object" ? this.toQuery(value, key) : !deep ? "" + key + "=" + value : "" + deep + "[" + key + "]=" + value);
            }
            return _results;
        }).call(this)).join("&");
    };
	/**
	 * Send request if method is POST send data in form-data
	 */
    Ajax.prototype.send = function() {
        if (this.method === "POST") {
            this.xmlhttp.send(this.data);
        } else {
            this.xmlhttp.send();
        }
    };

    return Ajax;

})();